home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1998-06-12 | 22.8 KB | 715 lines | [ TEXT/CWIE]
#if 0 Problem 13 - Legal Chess Moves Deep Thought has beaten mankind as the game once thought to exemplify human intuition. Our MacHack laboratory is secretly constructing an implant that will neutralize the calculation advantage held by the computer, and restore mankind to its rightful place as the champion of chess, through intuition and cunning. Your job is to write the code that will calculate the board position resulting from a sequence of moves, along with the legal moves available to the next player. With this advantage, the human chess master will be able to concentrate on strategy, rather than waste time calculating moves. The prototype for your solution is as follows: typedef enum {kEmpty=0,kWhite,kBlack} PieceColor; typedef enum {kNone=0,kPawn,kKnight,kBishop,kRook,kQueen,kKing} PieceRank; typedef struct Square { UInt16 row; /* 0..7, white initially occupies rows 0 and 1, black 7 and 6 */ UInt16 col; /* 0..7, white king starts at (row,col) == (0,4) */ } Square; typedef struct ChessMove { Square fromSquare; Square toSquare; Boolean capture; Square capturedSquare; /* valid only if capture==TRUE */ } ChessMove; typedef struct ChessPiece { PieceColor whichColor; PieceRank whichRank; Square pieceLocation; } ChessPiece; pascal void FindLegalChessMoves( UInt32 numPriorMoves, ChessMove priorMoves[], UInt32 *numPiecesRemaining, ChessPiece piecesRemaining[], UInt32 *numLegalMoves, ChessMove legalMoves[] ); Your FindLegalChessMoves routine will be called with a list (priorMoves) of numPriorMoves that have already taken place from the normal initial chessboard. You should model the effects of those moves and generate a list (piecesRemaining) of the numPiecesRemaining pieces remaining, including their location on the board, and a list (legalMoves) of all numLegalMoves legal moves available to the next player. Remember to include castling moves when appropriate (indicated by moving the king the appropriate two/three squares) and en passant pawn captures. #endif #include "Solution.h" // Fill in your solution and then submit this folder // Team Name: FILL IN YOUR TEAM NAME! #include "Solution.h" #include "ProblemUtils.h" #include "myqsort.h" #include <stdio.h> #include <Files.h> #include <Errors.h> #define PRINT_MOVES 0 #define PRINT_PIECES 0 #define PRINT_BOARD 0 #define kMaxPiecesRemaining 32 #define kMaxMoves 1024 static char gCol[] = "abcdefgh"; static char gRow[] = "12345678"; static char gColor[] = " WB"; static char gRank[] = "-pNBRQK"; #define kKingCol 4 #define kQueenCol 3 typedef struct Piece { PieceColor color; PieceRank rank; } Piece; typedef struct Board { Piece sq[8][8]; Square kingSq; ChessMove lastMove; Boolean pieceNeverMoved[8][8]; } Board; static void InitBoard(Board *b) { int row,col; for (col=0; col<8; col++) { b->sq[0][col].color = b->sq[1][col].color = kWhite; b->sq[7][col].color = b->sq[6][col].color = kBlack; b->sq[2][col].color = b->sq[3][col].color = kEmpty; b->sq[4][col].color = b->sq[5][col].color = kEmpty; b->sq[1][col].rank = b->sq[6][col].rank = kPawn; b->sq[2][col].rank = b->sq[3][col].rank = kNone; b->sq[4][col].rank = b->sq[5][col].rank = kNone; } b->sq[0][0] .rank= b->sq[0][7].rank = b->sq[7][0].rank = b->sq[7][7].rank = kRook; b->sq[0][1].rank = b->sq[0][6].rank = b->sq[7][1].rank = b->sq[7][6].rank = kKnight; b->sq[0][2].rank = b->sq[0][5].rank = b->sq[7][2].rank = b->sq[7][5].rank = kBishop; b->sq[0][kQueenCol].rank = b->sq[7][kQueenCol].rank = kQueen; b->sq[0][kKingCol].rank = b->sq[7][kKingCol].rank = kKing; for (row=0; row<8; row++) { for (col=0; col<8; col++) { b->pieceNeverMoved[row][col] = true; } } b->lastMove.fromSquare.row = b->lastMove.fromSquare.col = 0xffff; b->lastMove.toSquare.row = b->lastMove.toSquare.col = 0xffff; } #if PRINT_PIECES static void PrintPieces(UInt32 numPieces, ChessPiece *piece, char *s) { int j; printf("%s %ld\n", s,numPieces); for (j=0; j<numPieces; j++) { printf("%c%c %c%c\n", gColor[piece[j].whichColor],gRank[piece[j].whichRank], gCol[piece[j].pieceLocation.col],gRow[piece[j].pieceLocation.row]); } } #else static void PrintPieces(UInt32 numPieces, ChessPiece *piece, char *s) { #pragma unused(numPieces) #pragma unused(piece) #pragma unused(s) }; #endif #if PRINT_MOVES static void PrintMoves(UInt32 numMoves, ChessMove *move, char *s) { int j; printf("%s %ld\n",s,numMoves); for (j=0; j<numMoves; j++) { printf("%d %c%c%c%c%c",j, gCol[move[j].fromSquare.col],gRow[move[j].fromSquare.row], move[j].capture ? 'x' : '-', gCol[move[j].toSquare.col],gRow[move[j].toSquare.row]); if (move[j].capture) { printf(" %c%c\n", gCol[move[j].capturedSquare.col],gRow[move[j].capturedSquare.row]); } else { printf("\n"); } } } #else static void PrintMoves(UInt32 numMoves, ChessMove *move, char *s) { #pragma unused(numMoves) #pragma unused(move) #pragma unused(s) }; #endif #if PRINT_BOARD static void PrintBoard(Board *b) { int row,col; printf(" a b c d e f g h \n"); for (row=7; row>=0; row--) { printf("%2d ",row+1); for (col=0; col<8; col++) { printf("%c%c ",gColor[b->sq[row][col].color], gRank[b->sq[row][col].rank]); } printf("\n"); } printf(" %c%c%c%c%c\n\n", gCol[b->lastMove.fromSquare.col],gRow[b->lastMove.fromSquare.row], b->lastMove.capture ? 'x' : '-', gCol[b->lastMove.toSquare.col],gRow[b->lastMove.toSquare.row] ); } #else static void PrintBoard(Board *b) { #pragma unused(b) }; #endif static PieceColor OtherColor(PieceColor c) { return (PieceColor)(3 - (int)c); /* white is 1, black is 2 */ } static Boolean FindKing(Board *b,PieceColor color, Square *kingSq) { int row,col; for (row=0; row<8; row++) for (col=0; col<8; col++) { if ( (b->sq[row][col].color == color) && (b->sq[row][col].rank==kKing)) { kingSq->row = row; kingSq->col = col; return true; } } return false; } static void MovePiece(Board *b, ChessMove *m, PieceColor colorToMove) { int fromRow = m->fromSquare.row; int fromCol = m->fromSquare.col; int toRow = m->toSquare.row; int toCol = m->toSquare.col; PieceColor ourColor = b->sq[fromRow][fromCol].color; int homeRow = (ourColor==kWhite) ? 0 : 7; if (colorToMove != ourColor) printf("** ERR moving wrong color piece\n"); if (!m->capture) { if (b->sq[toRow][toCol].color != kEmpty) { printf(" ** bad move fromSq=(%d %d) toSq=(%d %d) our color=%d other color=%d\n", fromRow,fromCol,toRow,toCol, b->sq[fromRow][fromCol].color,b->sq[toRow][toCol].color); } } else { // debug test fails incorrectly for en passant // if (b->sq[toRow][toCol].color != OtherColor(b->sq[fromRow][fromCol].color)) { // printf(" ** bad capture fromSq=(%d %d) toSq=(%d %d) our color=%d other color=%d\n", // fromRow,fromCol,toRow,toCol, // b->sq[fromRow][fromCol].color,b->sq[toRow][toCol].color); // } /* includes en passant */ b->sq[m->capturedSquare.row][m->capturedSquare.col].color = kEmpty; b->sq[m->capturedSquare.row][m->capturedSquare.col].rank = kNone; } /* check castle */ if ( (b->sq[fromRow][fromCol].rank == kKing) && (fromRow==homeRow) && (fromCol==kKingCol) && (b->sq[fromRow][fromCol].color==ourColor) ) { if ( (toCol==2) && (b->sq[fromRow][1].rank==kRook)) { b->sq[fromRow][3].color = b->sq[fromRow][0].color; b->sq[fromRow][3].rank = b->sq[fromRow][0].rank; b->sq[fromRow][0].color = kEmpty; b->sq[fromRow][0].rank = kNone; } else if ( (toCol==6) && (b->sq[fromRow][7].rank==kRook) ) { b->sq[fromRow][5].color = b->sq[fromRow][7].color; b->sq[fromRow][5].rank = b->sq[fromRow][7].rank; b->sq[fromRow][7].color = kEmpty; b->sq[fromRow][7].rank = kNone; } } /* check pawn promotion */ if ( (b->sq[fromRow][fromCol].rank == kPawn) && (b->sq[fromRow][fromCol].color==ourColor) && (toRow==7-homeRow) ) { /* promote in place, move code will update proper location */ b->sq[toRow][toCol].rank = kQueen; } /* update board */ b->sq[toRow][toCol].color = b->sq[fromRow][fromCol].color; b->sq[toRow][toCol].rank = b->sq[fromRow][fromCol].rank; b->sq[fromRow][fromCol].color = kEmpty; b->sq[fromRow][fromCol].rank = kNone; b->pieceNeverMoved[fromRow][fromCol] = false; b->pieceNeverMoved[toRow][toCol] = false; b->lastMove = *m; FindKing(b,ourColor,&b->kingSq); } static SInt16 gDeltaRow[8] = { 0, 1, 1, 1, 0, -1, -1, -1}; static SInt16 gDeltaCol[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; static SInt16 gKnightDeltaRow[8] = {1,2,2,1,-1,-2,-2,-1}; static SInt16 gKnightDeltaCol[8] = {-2,-1,1,2,2,1,-1,-2}; static Boolean LegalSquare(SInt16 row, SInt16 col) { /* note need for signed value */ return ((row>=0) && (row<8) && (col>=0) && (col<8)); } static Boolean LegalRelSquare(Board *b, SInt16 row, SInt16 col, int dir, int dist, Piece *sq) { Boolean result; row += gDeltaRow[dir]*dist; col += gDeltaCol[dir]*dist; result = LegalSquare(row, col); if (result) *sq = b->sq[row][col]; return result; } static Boolean LegalKnightRelSquare(Board *b, SInt16 row, SInt16 col, int dir, Piece *sq) { Boolean result; row += gKnightDeltaRow[dir]; col += gKnightDeltaCol[dir]; result = LegalSquare(row,col); if (result) *sq = b->sq[row][col]; return result; } static Boolean MovesDiagonally(PieceRank rank, UInt16 dist) { return ((rank==kQueen)||(rank==kBishop)||( (dist==1) && (rank==kKing) ) ); } static Boolean MovesRectangularly(PieceRank rank, UInt16 dist) { return ((rank==kQueen)||(rank==kRook)||( (dist==1) && (rank==kKing) ) ); } static Boolean SquareIsAttacked(Board *b, SInt16 row, SInt16 col) { Piece onSquare; PieceColor ourColor = b->sq[row][col].color; PieceColor opponentColor = OtherColor(ourColor); int dir,dist; for (dir=1; dir<8; dir+=2) { /* check diagonals */ for (dist=1; dist<8; dist++) { /* check distance */ if (!LegalRelSquare(b, row, col, dir, dist, &onSquare)) break; if (onSquare.color == kEmpty) break; if (onSquare.color == ourColor) break; if (onSquare.color == opponentColor) { if ( MovesDiagonally(onSquare.rank,dist) ) return true; } else break; } } for (dir=0; dir<8; dir+=2) { /* check files */ for (dist=1; dist<8; dist++) { /* check distance */ if (!LegalRelSquare(b, row, col, dir, dist, &onSquare)) break; if (onSquare.color == kEmpty) break; if (onSquare.color == ourColor) break; if (onSquare.color == opponentColor) { if ( MovesRectangularly(onSquare.rank,dist) ) return true; } else { break; } } } for (dir=0; dir<8; dir++) { /* check knights */ if (!LegalKnightRelSquare(b, row, col, dir, &onSquare)) continue; if (onSquare.color == kEmpty) continue; if (onSquare.color == ourColor) continue; if ( (onSquare.color == opponentColor) && (onSquare.rank == kKnight) ) return true; } /* check pawns */ if (LegalRelSquare(b, row, col, (ourColor==kWhite) ? 1 : 8-1, 1, &onSquare)) if ( (onSquare.color==opponentColor) && (onSquare.rank==kPawn)) return true; if (LegalRelSquare(b, row, col, (ourColor==kWhite) ? 3 : 8-3, 1, &onSquare)) if ( (onSquare.color==opponentColor) && (onSquare.rank==kPawn)) return true; return false; } static void CreateMove(ChessMove *m, UInt16 row, UInt16 col, int dir, int dist, Piece *sq) { m->fromSquare.row = row; m->fromSquare.col = col; m->toSquare.row = row + gDeltaRow[dir]*dist; m->toSquare.col = col + gDeltaCol[dir]*dist; m->capture = false; if (sq->color != kEmpty) { /* pawns need to be handled separately */ m->capture = true; m->capturedSquare = m->toSquare; } } static void CreateKnightMove(ChessMove *m, UInt16 row, UInt16 col, int dir, Piece *sq) { m->fromSquare.row = row; m->fromSquare.col = col; m->toSquare.row = row + gKnightDeltaRow[dir]; m->toSquare.col = col + gKnightDeltaCol[dir]; m->capture = false; if (sq->color != kEmpty) { /* pawns need to be handled separately */ m->capture = true; m->capturedSquare = m->toSquare; } } static Boolean CheckMove(Board *origBoard, ChessMove **moves, SInt16 row, SInt16 col, int dir, int dist, Piece *onSquare,UInt32 *numMovesAdded) { ChessMove theMove; Board b = *origBoard; if (b.sq[row][col].rank == kKnight) { CreateKnightMove(&theMove,row,col,dir,onSquare); } else { CreateMove(&theMove,row,col,dir,dist,onSquare); } MovePiece(&b, &theMove, b.sq[row][col].color); if (SquareIsAttacked(&b, b.kingSq.row,b.kingSq.col)) {/* moves king into check or leaves king in check */ return false; } **moves = theMove; (*moves)++; ++*numMovesAdded; return true; } static Boolean CheckEPMove(Board *origBoard, ChessMove **moves, SInt16 row, SInt16 col, SInt16 captureRow, SInt16 captureCol,int dir, Piece *onSquare,UInt32 *numMovesAdded) { ChessMove theMove; Board b = *origBoard; CreateMove(&theMove,row,col,dir,1,onSquare); theMove.capturedSquare.row = captureRow; theMove.capturedSquare.col = captureCol; theMove.capture = true; MovePiece(&b, &theMove,b.sq[row][col].color); if (SquareIsAttacked(&b, b.kingSq.row,b.kingSq.col)) {/* moves king into check or leaves king in check */ return false; } **moves = theMove; (*moves)++; ++*numMovesAdded; return true; } static UInt32 CreateLegalPawnMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *origMoves) { PieceColor ourColor = origBoard->sq[row][col].color; PieceColor opponentColor = OtherColor(ourColor); UInt32 numMovesAdded = 0; Piece onSquare; int dir,dist,homeRow,advanceRowDir,enPassantRow; ChessMove *moves = origMoves; if (ourColor==kWhite) { dir = 2; enPassantRow = 4; advanceRowDir = 1; } else { dir = 8-2; enPassantRow = 7-4; advanceRowDir = -1; } dir = ourColor==kWhite ? 2 : 8-2; /* check moves ahead */ homeRow = (ourColor==kWhite) ? 1 : 7-1; /* home row is 1 for white and 6 for black */ /* check move one ahead */ dist = 1; if ( (LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) && (onSquare.color == kEmpty) ) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); } /* check move two ahead */ dist = 2; if ( (origBoard->pieceNeverMoved[row][col]) && (row == homeRow) && (LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) /* set onSquare */ && (onSquare.color == kEmpty) ){ CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); } /* check capture right (including en passant) */ dir = ourColor==kWhite ? 3 : 8-3; dist=1; if ( LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) { if (onSquare.color == opponentColor) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); } else { SInt16 epCol = col+gDeltaCol[dir]; if ( (onSquare.color == kEmpty) && (row==enPassantRow) && (origBoard->sq[row][epCol].rank == kPawn) && (origBoard->sq[row][epCol].color == opponentColor) && (origBoard->lastMove.toSquare.row == enPassantRow) && (origBoard->lastMove.fromSquare.row == enPassantRow+2*advanceRowDir) && (origBoard->lastMove.fromSquare.col == col + gDeltaCol[dir]) && (origBoard->lastMove.toSquare.col == col + gDeltaCol[dir]) ) { CheckEPMove(origBoard,&moves,row,col,row,epCol,dir,&onSquare, &numMovesAdded); // printf("** checking en passant (r,c)=(%d %d) ep=(%d %d)\n", // row,col,origBoard->lastMove.fromSquare.row,origBoard->lastMove.fromSquare.col); } } } /* check capture left (including en passant) */ dir = ourColor==kWhite ? 1 : 8-1; dist=1; if ( LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) { if (onSquare.color == opponentColor) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); } else { SInt16 epCol = col+gDeltaCol[dir]; if ( (onSquare.color == kEmpty) && (row==enPassantRow) && (origBoard->sq[row][epCol].rank == kPawn) && (origBoard->sq[row][epCol].color == opponentColor) && (origBoard->lastMove.toSquare.row == enPassantRow) && (origBoard->lastMove.fromSquare.row == enPassantRow-2*advanceRowDir) && (origBoard->lastMove.fromSquare.col == col + gDeltaCol[dir]) && (origBoard->lastMove.toSquare.col == col + gDeltaCol[dir]) ) { CheckEPMove(origBoard,&moves,row,col,row,epCol,dir,&onSquare, &numMovesAdded); // printf("** checking en passant (r,c)=(%d %d) ep=(%d %d)\n", // row,col,origBoard->lastMove.fromSquare.row,origBoard->lastMove.fromSquare.col); } } } return moves-origMoves; } static UInt32 CreateLegalKnightMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves) { PieceColor ourColor = origBoard->sq[row][col].color; PieceColor opponentColor = OtherColor(ourColor); UInt32 numMovesAdded = 0; Piece onSquare; int dir,dist=0; for (dir=0; dir<8; dir++) { if (!LegalKnightRelSquare(origBoard, row, col, dir, &onSquare)) continue; if (onSquare.color == ourColor) continue; if ((onSquare.color == opponentColor) || (onSquare.color == kEmpty) ){ CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); continue; } } return numMovesAdded; } static UInt32 CreateLegalBishopMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves) { PieceColor ourColor = origBoard->sq[row][col].color; PieceColor opponentColor = OtherColor(ourColor); UInt32 numMovesAdded = 0; Piece onSquare; int dir,dist; for (dir=1; dir<8; dir+=2) { for (dist=1; dist<8; dist++) { /* check distance */ if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) break; if (onSquare.color == ourColor) break; if (onSquare.color == opponentColor) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); break; } else if (onSquare.color == kEmpty) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); continue; } } } return numMovesAdded; } static UInt32 CreateLegalRookMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves) { PieceColor ourColor = origBoard->sq[row][col].color; PieceColor opponentColor = OtherColor(ourColor); UInt32 numMovesAdded = 0; Piece onSquare; int dir,dist; for (dir=0; dir<8; dir+=2) { for (dist=1; dist<8; dist++) { /* check distance */ if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) break; if (onSquare.color == ourColor) break; if (onSquare.color == opponentColor) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); break; } else if (onSquare.color == kEmpty) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); continue; } } } return numMovesAdded; } static UInt32 CreateLegalQueenMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves) { PieceColor ourColor = origBoard->sq[row][col].color; PieceColor opponentColor = OtherColor(ourColor); UInt32 numMovesAdded = 0; Piece onSquare; int dir,dist; for (dir=0; dir<8; dir++) { for (dist=1; dist<8; dist++) { /* check distance */ if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) break; if (onSquare.color == ourColor) break; if (onSquare.color == opponentColor) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); break; } else if (onSquare.color == kEmpty) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); continue; } } } return numMovesAdded; } static UInt32 CreateLegalKingMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves) { PieceColor ourColor = origBoard->sq[row][col].color; PieceColor opponentColor = OtherColor(ourColor); UInt32 numMovesAdded = 0; Piece onSquare; int dir,dist,homeRow; if (ourColor==kWhite) { homeRow = 0; } else { homeRow = 7; } for (dir=0; dir<8; dir++) { dist = 1; if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) continue; if (onSquare.color == ourColor) continue; if ( (onSquare.color == opponentColor) || (onSquare.color == kEmpty) ) { CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded); continue; } } if ( (row==homeRow) && (col==kKingCol) && origBoard->pieceNeverMoved[row][col] && !SquareIsAttacked(origBoard, row, col)) { ChessMove theMove; if ( origBoard->pieceNeverMoved[row][0] && !SquareIsAttacked(origBoard, row, 0) && !SquareIsAttacked(origBoard, row, 1) && !SquareIsAttacked(origBoard, row, 2) && !SquareIsAttacked(origBoard, row, 3) && origBoard->sq[row][1].color==kEmpty && origBoard->sq[row][2].color==kEmpty && origBoard->sq[row][3].color==kEmpty ) { theMove.fromSquare.row = row; theMove.fromSquare.col = col; theMove.toSquare.row = row; theMove.toSquare.col = 1; theMove.capture = false; *moves = theMove; (moves)++; ++numMovesAdded; } if ( origBoard->pieceNeverMoved[row][7] && !SquareIsAttacked(origBoard, row, 7) && !SquareIsAttacked(origBoard, row, 6) && !SquareIsAttacked(origBoard, row, 5) && origBoard->sq[row][6].color==kEmpty && origBoard->sq[row][5].color==kEmpty ) { theMove.fromSquare.row = row; theMove.fromSquare.col = col; theMove.toSquare.row = row; theMove.toSquare.col = 6; theMove.capture = false; *moves = theMove; (moves)++; ++numMovesAdded; } } return numMovesAdded; } static UInt32 CreateLegalMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves) { PieceRank rank = origBoard->sq[row][col].rank; UInt32 numMovesAdded = 0; switch (rank) { case kPawn: numMovesAdded = CreateLegalPawnMoves(origBoard,row,col,moves); break; case kKnight: numMovesAdded = CreateLegalKnightMoves(origBoard,row,col,moves); break; case kBishop: numMovesAdded = CreateLegalBishopMoves(origBoard,row,col,moves); break; case kRook: numMovesAdded = CreateLegalRookMoves(origBoard,row,col,moves); break; case kQueen: numMovesAdded = CreateLegalQueenMoves(origBoard,row,col,moves); break; case kKing: numMovesAdded = CreateLegalKingMoves(origBoard,row,col,moves); break; default: printf("** piece rank err %d\n",rank); numMovesAdded = 0; break; } return numMovesAdded; } static UInt32 FindRemainingPieces(Board *b, ChessPiece piece[]) { int row,col; UInt32 numPiecesRemaining = 0; for (row=0; row<8; row++) for (col=0; col<8; col++) if (b->sq[row][col].color != kEmpty) { piece[numPiecesRemaining].whichColor = b->sq[row][col].color; piece[numPiecesRemaining].whichRank = b->sq[row][col].rank; piece[numPiecesRemaining].pieceLocation.row = row; piece[numPiecesRemaining].pieceLocation.col = col; numPiecesRemaining++; } return numPiecesRemaining; } pascal void FindLegalChessMoves( UInt32 numPriorMoves, ChessMove priorMoves[], UInt32 *numPiecesRemaining, ChessPiece piecesRemaining[], UInt32 *numLegalMoves, ChessMove legalMoves[] ) { int i; SInt16 row,col; Board bd; UInt32 myNumLegalMoves = 0; UInt32 myNumPiecesRemaining = 0; PieceColor colorToMove = kWhite; InitBoard(&bd); PrintBoard(&bd); for (i=0; i<numPriorMoves; i++) { MovePiece(&bd,&priorMoves[i],colorToMove); PrintBoard(&bd); colorToMove = OtherColor(colorToMove); } myNumPiecesRemaining = FindRemainingPieces(&bd, piecesRemaining); for (row=0; row<8; row++) for (col=0; col<8; col++) if (bd.sq[row][col].color == colorToMove) myNumLegalMoves += CreateLegalMoves(&bd,row,col,legalMoves+myNumLegalMoves); *numPiecesRemaining= myNumPiecesRemaining; *numLegalMoves = myNumLegalMoves; }